3 * Copyright (c) 2017 Apple Inc. All rights reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #import "SafariExtensionHandler.h"
19 #import "SafariExtensionViewController.h"
21 //#define SHOW_BROWSE_COUNT 1
26 static void browseReply( DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context );
29 @interface SafariExtensionHandler ()
31 @property (strong) NSMutableDictionary * instanceD;
33 @property (strong) dispatch_queue_t instanceBrowseQ;
34 @property (assign) DNSServiceRef instanceRef; // Never released!!!
39 @implementation SafariExtensionHandler
43 if( self = [super init] )
46 self.instanceD = [NSMutableDictionary dictionary];
47 [self startInstanceBrowse];
53 - (void)validateToolbarItemInWindow:(SFSafariWindow *)window validationHandler:(void (^)(BOOL enabled, NSString *badgeText))validationHandler {
54 // This method will be called whenever some state changes in the passed in window. You should use this as a chance to enable or disable your toolbar item and set badge text.
55 (void)window; // Unused
56 validationHandler(YES, _instanceD.count ? [NSNumber numberWithInteger: _instanceD.count].stringValue : @"");
59 - (SFSafariExtensionViewController *)popoverViewController {
60 return [SafariExtensionViewController sharedController];
64 - (void)startInstanceBrowse
66 if( !_instanceBrowseQ )
68 self.instanceBrowseQ = dispatch_queue_create( "DNSAllServiceBrowse", DISPATCH_QUEUE_PRIORITY_DEFAULT );
69 dispatch_set_context( _instanceBrowseQ, (void *)CFBridgingRetain( self ) );
70 dispatch_set_finalizer_f( _instanceBrowseQ, finalizer );
73 dispatch_sync( _instanceBrowseQ, ^{
74 [_instanceD removeAllObjects];
77 DNSServiceErrorType error;
78 if( (error = DNSServiceBrowse( &_instanceRef, 0/*no flags*/, 0, @"_http._tcp".UTF8String, "", browseReply, (__bridge void *)self )) != 0 )
79 NSLog(@"DNSServiceBrowse failed error: %ld", error);
83 error = DNSServiceSetDispatchQueue( _instanceRef, _instanceBrowseQ );
84 if( error ) NSLog( @"DNSServiceSetDispatchQueue error: %d", error );
88 #pragma mark - Dispatch
90 static void finalizer( void * context )
92 SafariExtensionHandler *self = (__bridge SafariExtensionHandler *)context;
93 NSLog( @"finalizer: %@", self );
94 (void)CFBridgingRelease( (__bridge void *)self );
97 #pragma mark - DNS callbacks
99 static void browseReply( DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context )
101 (void)sdRef; // Unused
102 (void)interfaceIndex; // Unused
103 (void)errorCode; // Unused
104 SafariExtensionHandler *self = (__bridge SafariExtensionHandler *)context;
105 char fullNameBuffer[kDNSServiceMaxDomainName];
106 if( DNSServiceConstructFullName( fullNameBuffer, serviceName, regtype, replyDomain ) == kDNSServiceErr_NoError )
108 NSString *fullName = @(fullNameBuffer);
110 if( flags & kDNSServiceFlagsAdd )
112 [self.instanceD setObject: fullName
117 [self.instanceD removeObjectForKey: fullName];